package cn.seaboot.admin.id;

import io.swagger.v3.oas.annotations.media.Schema;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 序列 [t_sys_sequence]
 * <p>
 * 并不是很乐意使用 mysql 的自增 ID，原因有很多：
 * 首先，这不是所有数据库通用的特性，用起来本身就很奇怪；
 * 其次，在做业务的时候，如果不将数据插入，ID 值是不确定的，如果需要提前用到 ID，就不得不去修改业务流程。
 * <p>
 * 原理：逻辑非常简单，启动的时候，与数据库进行同步，之后完全由代码控制自增；
 * 缺陷：手动改数据库，产生冲突的 ID。
 *
 * @author ChenSS on  2019-03-25 11:40
 */
@Schema(description = "序列 [t_sys_sequence] 实体类")
public class Sequence implements Serializable {
    private static final long serialVersionUID = -3320165594465143751L;

    private AtomicLong value = new AtomicLong(0);
    /**
     * 序列名
     * <p>
     * 这个值是必须的，后期如果需要扩展序列管理功能，需要这个值进行匹配。
     */
    @Size(max = 32)
    @Schema(description = "序列名")
    private String name;
    /**
     * 步长
     */
    @NotNull
    @Schema(description = "步长")
    private long step = 1;

    public Sequence(String name) {
        this.name = name;
        // register self to manager
        SequenceManager.put(name, this);
    }

    /**
     * 获取序列的下一个值
     *
     * @return v
     */
    public long next() {
        return value.addAndGet(step);
    }

    /**
     * 获取序列的当前值
     *
     * @return v
     */
    public long value() {
        return value.get();
    }

    /**
     * 获取当前值对象
     *
     * @return value
     */
    public AtomicLong getValue() {
        return value;
    }

    /**
     * 设置初始值
     *
     * @param atomicLong 初始值
     */
    public void setValue(AtomicLong atomicLong) {
        this.value = atomicLong;
    }

    /**
     * 设置初始值
     *
     * @param start 初始值
     */
    public void setValue(long start) {
        this.value.set(start);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getStep() {
        return step;
    }

    public void setStep(long step) {
        this.step = step;
    }

    @Override
    public String toString() {
        return "Sequence{" +
                "name='" + name + '\'' +
                ", step=" + step +
                ", value=" + value +
                '}';
    }
}
